#ifndef _Faction_HPP_
#define	_Faction_HPP_
/*******************************************************************************
 ** Name: Faction.hpp                                                          **
 ** Description: Faction and faction objects                                   **
 **                                                                           **
 ** Open Source Initiative (OSI) Approved License                             **
 **                                                                           **
 ** The contents of this file are subject to the terms of the                 **
 ** Common Development and Distribution License, Version 1.0 only             **
 ** (the "License").  You may not use this file except in compliance          **
 ** with the License.                                                         **
 **                                                                           **
 ** You can find a copy of the license in the LICENSE file within             **
 ** this distribution or at $WIKI/display/GOVT/License-software.              **
 ** Software distributed under the License is distributed on an "AS IS"       **
 ** basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.           **
 ** See the License for the specific language governing permissions           **
 ** and limitations under the License.                                        **
 **                                                                           **
 ** When distributing Covered Code, include this CDDL header in each          **
 ** file and include the License file at $GAME_DIR/LICENSE.                   **
 ** If applicable, add the following below this header, with the indicated    **
 ** fields enclosed by brackets "[]" replaced with your own identifying       **
 ** information: Portions Copyright [yyyy] [name of copyright owner]          **
 **                                                                           **
 ** Copyright (c) 2009-2011  Barry Gian James <gian@gamingods.net>            **
 ** All rights reserved.                                                      **
 ******************************************************************************/
// Portions (c) 2012 Open Design Strategies, LLC.
// Modified $Date: 2012-08-14 20:47:30 -0600 (Tue, 14 Aug 2012) $ by $Author: unknown $
#define Faction_hpp_ID   "$Id: Faction.hpp 69068 2012-08-15 02:47:30Z unknown $"

#include <odb/core.hxx>
#include <vector>
#include <string>
//#include "common.hpp"
//#include "character.hpp"

#define DEFAULT_Faction_CP   38	// set here?

// The greatest inspiration for this level of Faction detail comes from
// Spycraft v1.0 Faction manual OGL content.  Pick it up if you don't
// own it and incorporate it into your Spycraft 2.0 game.

namespace agency
{

//! The visibility level of the Faction.
enum class visibility {
    undefined, cryptic, secretive, hitmiss, general, common
};

#pragma db object table("faction_visibility")
struct FactionVisibility
{
#pragma db id type("VARCHAR(16)")
	std::string	name_;
	std::string	desc_;
	ushort		cost_;
};

// TODO This should probably be in a world file somewhere
// TODO This should probably just be removed ~gian
enum class region {
    undefined, africa, asia, easteu, westeu, mideast, namerica, samerica, camerica
};

#pragma db object table("faction_region")
struct FactionRegion
{
#pragma db id auto
	entity_t	id_;
#pragma db type ("VARCHAR(16)")
	std::string	name_;
	ushort		cost_;
};

//! area of influence
//! agents get a bonus when operating/rolling against this sphere
enum class influence {
    undefined, business, law, military, judicial, govt, cultural, crime
};

#pragma db object table("faction_influence")
struct FactionInfluence
{
#pragma db id auto
	entity_t	id_;
#pragma db type ("VARCHAR(16)")
	std::string	name_;
	ushort		cost_;
};

//! influence quality
enum class quality {
    inferior, poor, average, good, excellent
};

#pragma db object table("faction_quality")
struct FactionQuality
{
#pragma db id auto
	entity_t	id_;
#pragma db type ("VARCHAR(16)")
	std::string	name_;
	std::string	desc_;
	ushort		cost_;
};

//! How prepared does the Faction make it's new field agents?
//! this can either give extra training points at char creation/joining
//! or offer specialized training players spend points to get
//! The number value is the Faction CP cost.
enum class preparation {
    none, ojt=0x05, orientation=0x0F, academy=0x10
};

//! how extensive is the training at this Faction
//! this training level determines the highest training course available
enum class training {
    undefined, seminar, outsourced, offsite, campus
};

#pragma db object table("faction_training")
struct FactionTraining
{
	#pragma db id auto
	entity_t	id_;
#pragma db type ("VARCHAR(16)")
	std::string	name_;
	ushort		cost_;
};

//! max level of specialist able to render aid in the field
enum class specialist {
    undefined, amateur, competent, trained, skilled, expert
};

#pragma db object table("faction_specialists")
struct FactionSpecialist
{
#pragma db id auto
	entity_t	id_;
#pragma db type ("VARCHAR(16)")
	std::string	name_;
	std::string	desc_;
	ushort		cost_;
};

//! the Faction's tolerance for its agents commiting crime
//! maybe this will effect the Faction's reputation?
enum class tolerance {
    zero,           //!< zero-tolerance for crimes
    threestrikes,   //!< three strikes and yer out
    blindeye,       //!< you haven't broken a law until you get caught
    endsmeans       //!< ends justifies the means. do what you must.
};

//! How well does the Faction value it's operatives?
enum class agentvalue {
    burn,       //!< the Faction is just out to burn you
    unknown,    //!< if you get caught, we don't know you
    strings,    //!< will pull strings to help you if you get caught
    asset       //!< agents are highly-valued assets
};

//! Some gear requires the appropriate license
enum class licensure {
    none,       //!< no license. vigilante group.
    law,        //!< law enforcement
    federal,    //!< federal Faction
    military,    //!< military
    banned
};

#pragma db object table("faction_license")
struct FactionLicensure
{
	#pragma db id auto
	entity_t faction_license_;
#pragma db type ("VARCHAR(16)")
	std::string	name_;
	ushort		cost_;
};

//! what assets are at the Faction's disposal?
//#pragma db value table("faction_assets")
enum class assets {
	AdvGarage = 1,
	AdvLab,
	Airstrip,
	Armory,
	Classroom,
	CloneLab,
	COMSEC,
	Dojo,
	FiringRange,
	Harbor,
	Hospital,
	HotLab,
	LawOffice,
	MediaStudio,
	MilitaryDepot,
	MotorPool,
	Prison,
	RecordsOffice,
	Satellites,
	TrainingGround,
	Arena,
	Casino,
	Castle,
	ChopShop,
	CommunityCollege,
	DentalClinic,
	DesertBootCamp,
	DocksideWarehouse,
	LobbyistHQ,
	ExoticGreenhouse,
	GovtBioFacility,
	MilitaryBase,
	Museum,
	Newspaper,
	NuclearPlant,
	Gulag,
	PoliceAcademy,
	PropagandaStudio,
	PublicRelations,
	SoftwareFirm,
	SuicideBombers,
	SwissBankAcct,
	TatooParlor,
	UniGeneticsLab
};

#pragma db object table("faction_assets")
struct FactionAssets
{
#pragma db id type ("VARCHAR(32)")
	std::string	name_;
	std::string	desc_;
	ushort		cost_;
	ushort		bonus_;
	entity_t	bonus_to_;
};

//#pragma db value table("faction_resources")
enum class resources {
	GreaseMonkey = 1,
	DARPA,
	Topgun,
	EliteGuard,
	FiltyStinkingRich,
	Dungeons,
	FleetSupport,
	HigherEdu,
	OpenSourceSoftware,
	WorseThanDeath,
	TrainingCompound,
	Smuggling,
	GraspTheMonkeyMind,
	TheInCrowd,
	ExoticPoisons,
	Arsenal,
	Hotzones,
	PrivatePier,
	MobileMedicalUnit,
	LegalCounsel,
	PublicSupport,
	CrewservedGunsmith,
	SelfDestructMechanism,
	Fleet,
	PrivateCollection,
	Propaganda,
	IndependentEnergy,
	TortureChambers,
	CorrectionalFacility,
	HardenedKillers,
	Fanatics,
	PublicSympathy,
	WorldwidePersonDB,
	SatelliteNetwork,
	SecureComms,
	Martyrs,
	FluidAssets,
	SecretIDMethod,
	BasicCloning
};

#pragma db object table("faction_resources")
struct FactionResources
{
#pragma db id type ("VARCHAR(32)")
	std::string	name_;
#pragma db type ("VARCHAR(128)")
	std::string	desc_;
	ushort		cost_;
	ushort		bonus_;
	entity_t	bonus_to_;
};

//! the flavor/style of the Faction
enum class methodology {
	undefined,
    insurection,    //!< focused on foreign govt instability
    infiltration,   //!< focused on b&e
    investigation,  //!< focused on investigating <whatever>
    appropriation,  //!< um, stealing :)
    wetwork,        //!< black ops, assassination
    paramilitary,   //!< military-style operations
    coverup         //!< false info dissemination, covering tracks, hiding secret
};

#pragma db object table("faction_methodology")
struct FactionMethodology
{
#pragma db id auto
	entity_t	id_;
#pragma db type ("VARCHAR(16)")
	std::string	name_;
	std::string	desc_;
	ushort		cost_;
	ushort		bonus_;
	entity_t	bonus_to_;
};

//enum class origin {
//	undefined,
//    secret,         //!< origin (maybe) lost in mists of time
//    founding,       //!< around time of founding of US
//    ww1,            //!< (1910-1925)
//    ww2,            //!< (1930-1945)
//    redscare,       //!< (1950-1960)
//    coldwar,        //!< (1960-1980)
//    glastnost,      //!< (1980-1990) "tear down that wall"
//    dotcom,         //!< (1990-2000) dot.com era
//    terror          //!< (2000-present) war on terror
//};

#pragma db object table("faction_origins")
struct FactionOrigin
{
#pragma db id type("VARCHAR(16)")
	entity_t	idname_;
#pragma db type ("VARCHAR(64)")
	std::string	timeframe_;
};

enum class deptnum
{
	Unassigned,S1,S2,S3,S4,S5,S6,S7
};

//enum class stated_intent
//{
//	advising,
//	apprehension,
//	control,
//	collection,
//	combat,
//	defense,
//	freedom,
//	investigation,
//	justice,
//	observation,
//	peace,
//	profit,
//	protection,
//	research,
//	security,
//	science,
//	stability,
//	support,
//	training
//};

#pragma db object table("faction_public_intent")
struct FactionIntent
{
#pragma db id type("VARCHAR(16)")
	std::string	idname_;
#pragma db type ("VARCHAR(256)")
	std::string	desc_;
};

enum class forte
{
	Unbreakable,		// +2 bonus fort save
	Unflappable,		// +2 bonus will save
	Uncanny,			// +2 bonus reflex save
	MasterStudents,		// +2 bonus academics check
	MasterCharmers,		// +2 bonus disposition/seduction
	MasterManipulators,	// +2 bonus blackmail/coercion
	MasterInterrogators,// +2 bonus interrogation
	MasterBrainwashers,	// +2 bonus brainwashing
	MasterTormentors,	// +2 bonus harassment
	MasterHackers,		// +2 bonus computers/electronics check
	MasterTrackers,		// +2 bonus search/surveillance
	MasterMotorists,	// +2 bonus maneuver or mechanic check
	MasterTricksters,	// +2 bonus bluff/disguise check
	MasterTravelers,	// +2 bonus language
	MasterDiplomats,	// +2 bureaucracy/diplomacy check
	MasterCryptographers,	// +2 crypto/forgery check
	MasterDetectives	// +2 gather info/surveillance check
};

#pragma db object table("faction_fortes")
struct FactionForte
{
	#pragma db id auto
	entity_t	id_;
#pragma db type ("VARCHAR(24)")
	std::string	name_;
	ushort		bonus_;
	entity_t	bonus_to_;
};

extern std::string	dept[];

}   /* namespace Faction */


//! Each Faction has a sphere of influence
struct FactionInfluence
{

};
//struct FactionInfluence
//{
//    Faction::influence   influence;
//    Faction::quality     quality;
//    Faction::region      region;
//};

//! Support for custom naming of rank structure in your Faction
struct RankStructure
{
    std::string    rank;
    int             lvl;
};

//! @struct FactionRoster
//! @brief structure to hold the Faction's roster of personnel
//#pragma db object table("faction_rosters")
#pragma db value
struct FactionRoster
{
	entity_t		idchar_;
	ushort			rank_;
	agency::deptnum dept_;
	bool			online_;
};

//! @struct ToolsRating
//! @brief The faction's tools rating
//#pragma db object table("faction_tools")
#pragma db value
struct ToolsRating
{
//	#pragma db id
//	entity_t	id_;
	ushort	K;	// tech
	ushort	S;	// support
	ushort	G;	// gadget
	ushort	T;	// tradecraft
	ushort	R;	// resource
	ushort	P;	// protective
	ushort	V;	// vehicle
	ushort	W;	// weapon
};

//! @struct HomeOffice
//! @brief A basic description of where/how/what the HO for the Faction is like.
#pragma db object table("faction_home_office")
struct HomeOffice
{
	HomeOffice() { }
	#pragma db id auto
	entity_t	id_;
	std::string	desc_;
};

//! @class HiddenAgenda
//! @brief The actual, true, hidden agenda of the Faction/faction.
#pragma db object table("faction_agenda")
class HiddenAgenda
{
public:
	HiddenAgenda() { }

	std::string &	Name() { return idname_; }
	std::string &	LevelBonus(ushort l);
	std::string &	Desc() { return desc_; }

private:
	friend class odb::access;
#pragma db id type("VARCHAR(45)")
	std::string	idname_;
	entity_t	lvl1_bonus_;
	entity_t	lvl2_bonus_;
	entity_t	lvl3_bonus_;
	entity_t	lvl4_bonus_;
	entity_t	lvl5_bonus_;
	entity_t	lvl6_bonus_;
	std::string	desc_;
};

//class Character;
//! @class Faction
//! @brief The field operative's employer
#pragma db object table("faction")
class Faction {
public:
    explicit Faction(const std::string &);
//    Faction(const Faction& orig);
    virtual ~Faction();
    Faction();

    static std::string StdFrenchRank(int r);
    static std::string StdMilRanks(int r);
    static std::string StdMarineRanks(int r);
    static std::string StdGovtRanks(int r);

    void	AgentLogin(std::string &n);
    void	AgentLogout(std::string &n);
    void	AddNewAgent(entity_t c);	// add to Faction
    void	RemoveAgent(entity_t c);
    void	PromoteAgent(entity_t c);
    void	DemoteAgent(entity_t c);

    // Getters
    const std::string &	 Name() const { return name_; }
    const std::string & Desc() const { return desc_; }
    const agency::visibility  Visibility() const { return vis_; }
    const int	AgentMembers() const { return memberAgent_; }
    const int 		HandlerMembers() const { return memberHandler_; }
    const int 		ControlMembers() const { return memberControl_; }
    const long 		Funds() const { return funds_; }
    const agency::region Region() const { return homeregion_; }
    const std::string &	Cover() { return cover_; }
    const std::string & 	PublicIntent() const { return pubintent_; }
    const agency::training	Training()const  { return training_; }
    const agency::specialist  Specialists() const { return specialists_; }
    const agency::forte 	Forte() const { return forte_; }
    const agency::assets 	Assets() const { return assets_; }
    const entity_t		ID() const { return id_; }
    const std::string &	Origin() const { return origin_; }
    const entity_t	Owner() const { return idowner_; }
    const agency::resources Resources() const { return resources_; }

    // Setters
    void	Name(std::string & n) { name_ = n; }
    void	Visibility(const agency::visibility v) { vis_ = v; }
    void	Owner(const entity_t o) { idowner_ = o; }
    void	Desc(const std::string & d) { desc_ = d; }

private:
    friend class odb::access;

	#pragma db id auto
    entity_t		id_;
    std::string    	name_;			//!< name of the faction
    entity_t		tools_;
//    std::string		owner_type_;
    entity_t		idowner_;
//    entity_t		idpc_;
//    entity_t		idnpc_;
    std::string		desc_;
    entity_t		idranks_;
    entity_t	agenda_;
    entity_t		idawareness_;
    entity_t		home_office_;
    entity_t		idlicense_;
    entity_t		idpublic_agenda_;
    entity_t		idorigins_;
    entity_t		idsphere_;
    entity_t		idtraining_;
    agency::visibility      vis_;
    int				memberAgent_;	//!< # of member agents
    int				memberHandler_;
    int				memberControl_;
    long            funds_;
    agency::region  homeregion_;
    std::string    cover_;  //!< this is the cover story/business of the Faction
    // FIXME this needs to be converted to work with ODB ORM
    //std::string    ranks[20];
#pragma db type ("VARCHAR(16)")
    std::string		pubintent_;
#pragma db unordered
    std::vector<FactionRoster>	active_roster_;
    agency::training training_;
    agency::specialist specialists_;
    agency::forte	forte_;
#pragma db type ("VARCHAR(16)")
    std::string	origin_;

    agency::resources	resources_;
    agency::assets		assets_;

};


#endif	/* _Faction_HPP_ */

